// Copyright (c) 2007 Alistair Jones
// This program is made available under the terms of the MIT License.
package org.hypirinha.html.codegen;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;

import java.util.Set;

public class ChildElementFinderTest {

    @Test
    public void shouldListElementsThatAreDirectlyReferencedInTheElementDeclaration() {
        String miniSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<xs:schema version=\"1.0\" xml:lang=\"en\"\n" +
                "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +
                "  <xs:element name=\"html\">\n" +
                "    <xs:complexType>\n" +
                "      <xs:sequence>\n" +
                "        <xs:element ref=\"head\"/>\n" +
                "        <xs:element ref=\"body\"/>\n" +
                "      </xs:sequence>\n" +
                "    </xs:complexType>\n" +
                "  </xs:element>\n" +
                "</xs:schema>";

        Set<String> elements = new ChildElementFinder(new SchemaParser().parse(miniSchema)).findChildren("html");

        assertEquals(2, elements.size());
        assertTrue(elements.contains("head"));
        assertTrue(elements.contains("body"));
    }
    
    @Test
    public void shouldFollowLinksToGroupDeclarations() {
        String miniSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<xs:schema version=\"1.0\" xml:lang=\"en\"\n" +
                "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +
                "  <xs:element name=\"map\">\n" +
                "    <xs:complexType>\n" +
                "      <xs:group ref=\"misc\"/>\n" +
                "      <xs:element ref=\"area\"/>\n" +
                "    </xs:complexType>\n" +
                "  </xs:element>" +
                "  <xs:group name=\"misc\">\n" +
                "    <xs:element ref=\"noscript\"/>\n" +
                "  </xs:group>" +
                "</xs:schema>";

        Set<String> elements = new ChildElementFinder(new SchemaParser().parse(miniSchema)).findChildren("map");

        assertEquals(2, elements.size());
        assertTrue(elements.contains("noscript"));
        assertTrue(elements.contains("area"));
    }

    @Test
    public void shouldFollowSecondOrderLinksToGroupDeclarations() {
        String miniSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<xs:schema version=\"1.0\" xml:lang=\"en\"\n" +
                "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +
                "  <xs:element name=\"map\">\n" +
                "    <xs:complexType>\n" +
                "      <xs:group ref=\"misc\"/>\n" +
                "      <xs:element ref=\"area\"/>\n" +
                "    </xs:complexType>\n" +
                "  </xs:element>" +
                "  <xs:group name=\"misc\">\n" +
                "    <xs:element ref=\"noscript\"/>\n" +
                "    <xs:group ref=\"misc.inline\"/>" +
                "  </xs:group>" +
                "  <xs:group name=\"misc.inline\">\n" +
                "    <xs:choice>\n" +
                "      <xs:element ref=\"ins\"/>\n" +
                "      <xs:element ref=\"del\"/>\n" +
                "    </xs:choice>\n" +
                "  </xs:group>" +
                "</xs:schema>";

        Set<String> elements = new ChildElementFinder(new SchemaParser().parse(miniSchema)).findChildren("map");

        assertEquals(4, elements.size());
        assertTrue(elements.contains("noscript"));
        assertTrue(elements.contains("area"));
        assertTrue(elements.contains("ins"));
        assertTrue(elements.contains("del"));
    }

    @Test
    public void shouldTerminateWhenConfrontedWithRecursiveGroupDeclarations() {
        String miniSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<xs:schema version=\"1.0\" xml:lang=\"en\"\n" +
                "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +
                "  <xs:element name=\"map\">\n" +
                "    <xs:complexType>\n" +
                "      <xs:group ref=\"misc\"/>\n" +
                "      <xs:element ref=\"area\"/>\n" +
                "    </xs:complexType>\n" +
                "  </xs:element>" +
                "  <xs:group name=\"misc\">\n" +
                "    <xs:element ref=\"noscript\"/>\n" +
                "    <xs:group ref=\"misc.inline\"/>" +
                "  </xs:group>" +
                "  <xs:group name=\"misc.inline\">\n" +
                "    <xs:group ref=\"misc\"/>" +
                "  </xs:group>" +
                "</xs:schema>";

        Set<String> elements = new ChildElementFinder(new SchemaParser().parse(miniSchema)).findChildren("map");

        assertEquals(2, elements.size());
        assertTrue(elements.contains("noscript"));
        assertTrue(elements.contains("area"));
    }
    
    @Test
    public void shouldFollowExtensionLinksToComplexTypeDeclarations() {
        String miniSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<xs:schema version=\"1.0\" xml:lang=\"en\"\n" +
                "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +
                "  <xs:element name=\"noscript\">\n" +
                "    <xs:complexType>\n" +
                "      <xs:complexContent>\n" +
                "        <xs:extension base=\"Block\">\n" +
                "          <xs:attributeGroup ref=\"attrs\"/>\n" +
                "        </xs:extension>\n" +
                "      </xs:complexContent>\n" +
                "    </xs:complexType>\n" +
                "  </xs:element>" +
                "  <xs:complexType name=\"Block\">\n" +
                "    <xs:choice>\n" +
                "      <xs:group ref=\"block\"/>\n" +
                "      <xs:element ref=\"form\"/>\n" +
                "    </xs:choice>\n" +
                "  </xs:complexType>" +
                "  <xs:group name=\"block\">\n" +
                "    <xs:choice>\n" +
                "      <xs:element ref=\"p\"/>\n" +
                "    </xs:choice>\n" +
                "  </xs:group>" +
                "</xs:schema>";

        Set<String> elements = new ChildElementFinder(new SchemaParser().parse(miniSchema)).findChildren("noscript");

        assertEquals(2, elements.size());
        assertTrue(elements.contains("form"));
        assertTrue(elements.contains("p"));
    }

}